package org.bjf.utils;

import com.alibaba.fastjson.JSONObject;
import java.util.Map;
import java.util.TreeMap;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;

/**
 * 签名工具类
 *
 * @author binjinfeng
 * @desc 签名算法 1. 所有请求参数按key升序排序，如：a=zz&b=jj&c=rr&timestamp=1524630698729 2. 数组不参与签名 3. 把字符串
 * appKey=good_body  拼接到字符串的头部和尾部，然后进行64位的MD5签名，再把签名结果转化成大写。 示例： md5(good_bodya=zz&b=jj&c=rr&timestamp=1524630698729good_body).toUpperCase(),签名值为：0FF06E1F817C8644BADFB1504420A43C
 */
@Slf4j
public class SignUtil {

  private static final String SIGN_KEY = "good_body";

  public static String sign(Map<String, String> param) {
    return sign(param, SIGN_KEY);
  }

  public static String sign(Map<String, String> param, String signKey) {

    log.info("签名前数据:{}", JSONObject.toJSONString(param));

    //===1.按key字典排序及移除不参与签名的字段
    TreeMap<String, String> sortedMap = new TreeMap<>(param);
    sortedMap.remove("sign");

    //===2.组装签名字符串
    StringBuilder sb = new StringBuilder();
    sb.append(signKey);
    for (Map.Entry<String, String> entry : sortedMap.entrySet()) {
      String value = entry.getValue();
      if (StringUtils.isNotBlank(value)) {
        //空串不参数签名
        sb.append(entry.getKey()).append("=").append(value).append("&");
      }
    }
    sb.deleteCharAt(sb.lastIndexOf("&"));
    sb.append(signKey);

    //===3.MD5签名
    log.info("签名字符串:{}", sb.toString());
    String sign = DigestUtils.md5Hex(sb.toString()).toUpperCase();
    log.info("MD5签名:{}", sign);
    return sign;
  }
}